﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Samples.ServiceHosting.StorageClient;
using Ciripescu_WebRole.Entities;
using System.Data.Services.Client;
using System.Security.Cryptography;
using System.Text;
using System.Linq.Expressions;
using System.Data.Linq.SqlClient;

namespace Ciripescu_WebRole.BL
{
    public class UserManager
    {

        #region Public Methods

        public UserManager()
        {
            m_svcContext             = new MyServiceContext();
            m_svcContext.RetryPolicy = RetryPolicies.RetryN(3, TimeSpan.FromSeconds(1));
        }

        public IEnumerable<User> DoQuery(IQueryable<User> q)
        {
            TableStorageDataServiceQuery<User> query = new TableStorageDataServiceQuery<User>(q as DataServiceQuery<User>);
            IEnumerable<User> queryResults           = query.ExecuteAllWithRetries();
            return queryResults;
        }

        public User GetItem(string userName)
        {
            try
            {
                return (DoQuery(from c in m_svcContext.Users where c.PartitionKey == userName.ToLower() select c)).Single();
            }
            catch (Exception e)
            {                
                return null;
            }
        }

        public bool UserNameExists(string userName)
        {
            try
            {
                string lowUser = userName.ToLower();
                var lista = GetAllItems();                
                foreach (User u in lista)
                    if (u.PartitionKey.ToLower() == lowUser)
                        return true;
                return false;
            }
            catch (Exception e)
            {
                Utils.WriteLog(EventLogName.Error, e.ToString());
                return true;
            }
        }

        public User GetItemByEmail(string email)
        {
            try
            {
                return (DoQuery(from c in m_svcContext.Users where c.Email.CompareTo(email.ToLower()) == 0 select c)).Single();
            }
            catch (Exception e)
            {
                Utils.WriteLog(EventLogName.Error, e.ToString());
                return null;
            }
        }

        public User GetItem(string userName, string password)
        {
            User usr = null;
            try
            {
                usr =  (DoQuery(from c in m_svcContext.Users
                                where c.PartitionKey == userName.ToLower() 
                                select c)).Single();

                string a = Utils.MD5Crypt(password);
                if (a.CompareTo(usr.Password) != 0)
                    usr = null;
            }
            catch (Exception ex)
            {
                Utils.WriteLog(EventLogName.Error, ex.ToString());
                return null;
            }

            return usr;
        }
        public List<User> GetItemsByPartialUserName(string userName, bool contains)
        {
            List<User> lista = GetAllItems().ToList();
            if (userName == "")
                return lista;
            List<User> result = new List<User>();
            foreach (User u in lista)
            {
                if (contains)
                {
                    if (u.PartitionKey.Contains(userName.ToLower()))
                        result.Add(u);
                }
                else
                    if (u.PartitionKey.StartsWith(userName.ToLower()))
                        result.Add(u);
            }
            return result;
        }

        public IEnumerable<User> GetAllItems()
        {
            var results = from c in m_svcContext.Users select c;
            return DoQuery(results);
        }

        public void Delete(User itemToDelete)
        {
            m_svcContext.DeleteObject(itemToDelete);
            m_svcContext.SaveChanges();
        }

        public void DeleteWithoutQ(User itemToDelete)
        {
            m_svcContext.AttachTo(m_svcContext.UsersTableName, itemToDelete, "*");
            Delete(itemToDelete);
        }

        /// <summary>
        /// Updates an existing item from the tables.
        /// </summary>
        /// <param name="item"></param>
        public void Save(User item)
        {
            // daca obiectul din Storage nu are ultima versiune fa update cu proprietatile lipsa
            if (item.Version == "0.1")
            {
                //item.Votes = 0;
                //item.IsAdmin = false;
                item.Version = Properties.Settings.Default.Version;
            }
            m_svcContext.UpdateObject(item);
            m_svcContext.SaveChanges();
        }

        /// <summary>
        /// Insert a new item in the tables.
        /// </summary>
        /// <param name="newItem"></param>
        public void Insert(User newItem)
        {
                m_svcContext.AddObject(m_svcContext.UsersTableName, newItem);
                m_svcContext.SaveChanges();
        }
        

        /// <summary>
        /// Returns true if the first user follows the second user.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="onUser"></param>
        /// <returns></returns>
        public bool Follows(string firstUser, string secondUser)
        {
            bool f = true;

            UrmarireManager urmManag = new UrmarireManager();
            if (urmManag.GetItem(firstUser, secondUser) == null)
                f = false;

            return f;
        }

        /// <summary>
        /// Searches a users with name like given input string.
        /// </summary>
        /// <param name="searchFor"></param>
        /// <returns></returns>
        public List<User> Search(string searchFor)
        {
            //var q = from u in m_svcContext.Users
            //        where SqlMethods.Like(u.PartitionKey, "%" + searchFor + "%")
            //        select u;
            
            IEnumerable<User> allUsers = GetAllItems();
            List<User> result = new List<User>();

            try
            {
                searchFor = searchFor.ToLower();
                foreach (User u in allUsers.ToList<User>())
                    if (u.PartitionKey.Contains(searchFor))
                        result.Add(u);
                    else
                    {
                        //search for a half of text
                        string halfSearchFor = String.Empty;
                        if (!string.IsNullOrEmpty(searchFor) && searchFor.Length >= 6) //minum of 6 characters for search text
                            halfSearchFor = searchFor.Substring(0, searchFor.Length / 2);
                        if (!string.IsNullOrEmpty(halfSearchFor))
                            if (u.PartitionKey.Contains(halfSearchFor))
                                result.Add(u);
                    }
            }
            catch (ArgumentNullException ex)
            {
                Utils.WriteLog(EventLogName.Warning, ex.ToString());
            }
            catch (Exception ex)
            {
                Utils.WriteLog(EventLogName.Warning, ex.ToString());
            }

            return result;
        }

        
        #endregion

        #region Private Methods


        #endregion 

        #region Private Members

        private MyServiceContext m_svcContext = null;
        
        #endregion

        
    }
}
